package server.gui;

import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.sql.SQLException;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;

import model.Usuario;
import server.console.Consola;
import server.exception.ServiceException;
import server.gui.controller.ConsoleController;
import server.services.ServerService;
import server.services.UsuarioService;
import client.Configuration;

@SuppressWarnings("serial")
public class PantallaPrincipal extends JFrame {

	private JPanel contentPane;
	private JTextField textFieldComando;
	private DefaultListModel<String> mensajes;
	private ServerService service;
	private UsuarioService usuarioService;
	private DefaultListModel<Usuario> usuariosConectados;
	private JList<Usuario> listUsuarios;
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					PantallaPrincipal frame = new PantallaPrincipal();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public PantallaPrincipal() {
		service = new ServerService();
		usuarioService = new UsuarioService();
		super.addWindowListener(new WindowListener() {
			
			@Override
			public void windowOpened(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void windowIconified(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void windowDeiconified(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void windowDeactivated(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void windowClosing(WindowEvent e) {
				
				try {
					usuarioService.close();
				} catch (SQLException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			
			@Override
			public void windowClosed(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void windowActivated(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}
		});
		
		setTitle("Consola de Administracion");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 850, 768);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		JLabel lblMensajesActuales = new JLabel("Mensajes actuales");
		lblMensajesActuales.setFont(new Font("Tahoma", Font.PLAIN, 16));
		lblMensajesActuales.setBounds(20, 11, 185, 26);
		contentPane.add(lblMensajesActuales);

		mensajes = new DefaultListModel<>();
		JList<String> listMensajes = new JList<String>(mensajes);
		JScrollPane list = new JScrollPane(listMensajes);
		list.setBounds(20, 48, 563, 554);
		listMensajes.addMouseListener(ConsoleController
				.getConsoleListItemClick());
		contentPane.add(list);
		bindConsole();

		JSeparator separator = new JSeparator();
		separator.setOrientation(SwingConstants.VERTICAL);
		separator.setBounds(603, 11, 11, 708);
		contentPane.add(separator);

		usuariosConectados = new DefaultListModel<>();
		listUsuarios = new JList<Usuario>(usuariosConectados);
		listUsuarios.setBounds(624, 48, 185, 457);
		listUsuarios.addMouseListener(new MouseAdapter() {
			@SuppressWarnings("unchecked")
			public void mouseClicked(MouseEvent evt) {
				if(evt.getClickCount() >= 2) {
					JList<Usuario> lista = (JList<Usuario>) evt.getComponent();
					int indice = lista.getSelectedIndex();
					if (indice >= 0) {
						ListModel<Usuario> listaModel = lista.getModel();
						Usuario usuario = listaModel.getElementAt(indice);
						int response = JOptionPane.showConfirmDialog(null, "¿Desea desconectar a <" + usuario + "> ?",
													  "Desconectar usuario", JOptionPane.YES_NO_OPTION);
						if (response == JOptionPane.YES_OPTION)
							desconectar(usuario);
					}
				}
			}
		});
		contentPane.add(listUsuarios);
		actualizarListaUsuarios();

		JLabel lblUsuarios = new JLabel("Usuarios");
		lblUsuarios.setFont(new Font("Tahoma", Font.PLAIN, 16));
		lblUsuarios.setBounds(635, 19, 97, 18);
		contentPane.add(lblUsuarios);

		JButton btnPenalizarA = new JButton("Penalizar a...");
		btnPenalizarA.setBounds(635, 537, 161, 23);
		btnPenalizarA.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						try {
							PantallaPenalizacion frame = new PantallaPenalizacion();
							frame.setVisible(true);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});
			}
		});
		contentPane.add(btnPenalizarA);

		JButton btnEnviarMensajeA = new JButton("Enviar mensaje a...");
		btnEnviarMensajeA.setBounds(635, 579, 161, 23);
		btnEnviarMensajeA.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						try {
							PantallaEnviarMensaje frame = new PantallaEnviarMensaje();
							frame.setVisible(true);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});
			}
		});
		contentPane.add(btnEnviarMensajeA);

		JButton btnDetenerServidor = new JButton("Iniciar/Detener Servidor...");
		btnDetenerServidor.setBounds(635, 644, 161, 41);
		btnDetenerServidor.addActionListener(getALPararServidor());
		contentPane.add(btnDetenerServidor);

		textFieldComando = new JTextField();
		textFieldComando.setFont(new Font("Tahoma", Font.PLAIN, 15));
		textFieldComando.setBounds(20, 644, 563, 41);
		contentPane.add(textFieldComando);
		textFieldComando.setColumns(10);
		textFieldComando.addActionListener(ConsoleController
				.getConsoleActionListener(textFieldComando));

		JLabel lblComandos = new JLabel("Comandos");
		lblComandos.setBounds(22, 619, 104, 14);
		contentPane.add(lblComandos);
	}

	private void bindConsole() {
		Consola consola = Consola.getInstance();
		consola.setOut(ConsoleController.getPrintStream(mensajes));
	}

	private ActionListener getALPararServidor() {
		return new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				// Si el servidor no esta activo
				if (!service.isActivo()) {
					String port = JOptionPane.showInputDialog(
							"Ingrese el puerto",
							String.valueOf(Configuration.PUERTO_CONEXION));
					try {
						service.iniciar(Integer.valueOf(port));
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(null,
								"Ingrese un puerto correcto\n",
								"Error de validacion",
								JOptionPane.ERROR_MESSAGE);
					} catch (ServiceException e) {
						JOptionPane.showMessageDialog(
								null,
								"No se ha podido iniciar el servicio\n"
										+ e.getMessage(),
								"Error al iniciar el servicio",
								JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					}

					// Si el servidor esta activo
				} else {
					EventQueue.invokeLater(new Runnable() {
						public void run() {
							try {
								PantallaDetenerServidor frame = new PantallaDetenerServidor();
								frame.setVisible(true);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					});
				}
			}
		};
	}

	private void actualizarListaUsuarios() {
		Thread t = new Thread(new Runnable() {
			public void run() {
				while (true) {
					try {
						usuariosConectados.removeAllElements();
						for (Usuario usuario : usuarioService.conectados())
							usuariosConectados.addElement(usuario);

						Thread.sleep(1000);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
		t.start();
	}
	
	private void desconectar(Usuario u) {
		try {
			usuarioService.desconectar(u);
		} catch (Exception e) {
			JOptionPane.showMessageDialog(
					null,
					"No se pudo desconectar al cliente\n"
							+ e.getMessage(),
							"Error al iniciar el servicio",
							JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
		}
	}
}
